package com.wx.task.service;

import com.wx.task.controller.AsyncController;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor;
import org.springframework.stereotype.Service;
import org.springframework.scheduling.annotation.ProxyAsyncConfiguration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * 异步执行的实现原理:
 * 1. @EnableAsync 开启异步注解功能，也就是向容器中注入了 {@link ProxyAsyncConfiguration} 配置类
 * 2. {@link ProxyAsyncConfiguration} 配置类向容器中注入了 {@link AsyncAnnotationBeanPostProcessor}
 * 3. {@link AsyncAnnotationBeanPostProcessor} 实现了 BeanPostProcessor 接口
 * 4. 所以在每一个 Bean 实例化的过程中都会执行 BeanPostProcessor 的 before 和 after 的后置方法
 * 5. 在执行 after 的后置方法的过程中会判断每一个 Bean 中的每一个方法是否标注 @Async 注解
 * 6. 如果某一个 Bean 中的方法上标注了 @Async 注解，那么会对此 Bean 生成代理对象
 * 7. 如果此 Bean 实现了接口，那么使用 JDK 动态代理，否则使用 CgLIB 动态代理
 * 8. 代理类的执行逻辑就是使用 [线程池] 来调用执行目标类中的方法，首先从容器中获取这个线程池，容器中获取到了就是用获取到的，否则使用默认的
 * 9. 如果我们自定义了线程池，就使用我们自定义的，否则使用默认的 new SimpleAsyncTaskExecutor()，[线程池]我们可以自定义，自定义之后放到容器中即可
 */
@Service
public class AsyncServiceImpl implements AsyncService {

    // 告诉 Spring 这是一个异步方法，底层使用线程池来执行
    @Async
    @Override
    public void hello() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("AsyncService -- hello()");
    }

    @Async
    @Override
    public void hi() {

        ServletRequestAttributes request12 = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());
        System.out.println(request12);

        System.out.println(AsyncController.inheritableRequestAttributesHolder.get());

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("AsyncService -- hello()");
    }
}
